/*
 * Copyright (C) 2010 The Android Open Source Project 
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at 
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and 
 * limitations under the License.
 */

package org.lhlzi.ithink;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;

import org.lhlzi.ithink.dao.CallLogDao;
import org.lhlzi.ithink.dao.EventObserver;
import org.lhlzi.ithink.model.IRecentContactChangedListener;
import org.lhlzi.ithink.model.RecentContact;
import org.lhlzi.ithink.model.RecentEvent;

import android.app.Activity;
import android.app.ListActivity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.provider.CallLog;
import android.provider.CallLog.Calls;
import android.text.format.DateFormat;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;

public class IphoneCallLogScreen extends Activity {

	public static final String TAG = IphoneCallLogScreen.class.toString();
	
	public final static String ACTION = "org.lhlzi.ithink.UPDATE";
	
	
	private IphoneCallLogAdapter lvAdapter = null;
	/* It is not a static object,because of this not necessary(not only not improve
	 * performance but also waste memory).
	 */
	public static List<HashMap<String, Object>> listItem = new ArrayList<HashMap<String, Object>> ();
	public static List<RecentContact> recentContacts = new ArrayList<RecentContact>();
	private static DataCacheWrapper dataCacheWrapper = DataCacheWrapper.getInstance();
	private EventObserver observer;
	/* It's a pivotal variable for check if call log record is 
	 * changed in database.
	 */
	public static int mRecords = 0;
	/*
	 * Make sure <code>DataLoading</code> async task just
	 * run once.
	 */
	private static boolean mRunning = false;
	private ListView lv = null;
//	private Handler dismissDialog = null;
	
	private static final String[] projection = new String[]{
			Calls.NUMBER,
			Calls.TYPE,
			Calls.NEW,
		};
	
	private static final String[] fromFields = new String[]{
		"name",
		"eventcounts",
		"calltype",
		"location",
		"date",
	};
	
	private static final int[] toFields = new int[]{
		R.id.displayname,
		R.id.eventcounts,
		R.id.calltype,
		R.id.location,
		R.id.date,
	};

	
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		setContentView(R.layout.recents);
		
//		mRecords = recentContacts.size();
		
//		Log.i(TAG, "static RecentContacts [size=" + recentContacts.size() + "],[mRecords=" + mRecords + "],[listItem is null?" + (listItem == null) + "]");
		
		
		
		// 监视通话记录的变动，实时更新ListView控件
		callLogObserver = new CallLogNotificationObserver(this, new Handler());
		
		lv = (ListView) findViewById(R.id.list);
		
		lvAdapter = new IphoneCallLogAdapter(IphoneCallLogScreen.this, listItem, 
				R.layout.recent_row,
				fromFields, 
				toFields);
		
		lv.setAdapter(lvAdapter);
		
		if (listItem == null || listItem.size() == 0 
				|| mRecords != getCount()) {
			String action = null;
			
			if (getCount() - mRecords == 1) {
				action = ACTION;
			}
			new DataLoading().execute(action);
		}
		
		
	}

	
	private int getCount() {
		Cursor c = getContentResolver()
		.query(Calls.CONTENT_URI, 
				projection, 
				null, null, 
				Calls.DEFAULT_SORT_ORDER);
		
		if (c != null) {
			return c.getCount();
		}
		
		return 0;
	}
	
	class DataLoading extends AsyncTask<String, Object, Void> implements IRecentContactChangedListener {
		
		@Override
		protected Void doInBackground(String... params) {
			
			Intent intent = null;
			
			if (params.length > 0 && params[0] != null)
				intent = new Intent(params[0]);
			
			buildRecentEvents(IphoneCallLogScreen.this, intent, this);
			
			return null;
		}
		
		protected void onProgressUpdate(Object...objects) {
			
			if (lvAdapter == null) {
				//cancel(true);
				return;
			}
			
			fillListItem((Integer)objects[0], (RecentContact)objects[1], false);
			
			lvAdapter.notifyDataSetChanged();
			
		}
		@Override
		protected void onPostExecute(Void param) {
			mRunning = false;
			
			if (listItem != null && listItem.size() == 0)
				lvAdapter.notifyDataSetChanged();
			
			Log.i(TAG, "ListItem [size=" + listItem.size() + "], RecentContacts [size=" +
					recentContacts.size() + "]");
		}

		@Override
		public void onRecentContactChanged(int location,
				RecentContact recentContact) {
			
			if (recentContact != null && !isCancelled()) {
				publishProgress(location, recentContact);
			}
			
			
		}
	}
	
	
	public static void callNumber(Context context, int position) {
		Intent intent = new Intent(Intent.ACTION_CALL);
		intent.setData(Uri.parse("tel:"+recentContacts.get(position).getNumber()));
		intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
		context.startActivity(intent);
	}
	
	
	
	public static void showDetail(Context context, int position) {
		IphoneCallLogDetails.showActivity(context, recentContacts.get(position), dataCacheWrapper);
	}
	
	
	/**
	 * Fill data to <code>ListItem</code>.
	 */
	private void fillListItem(int location, RecentContact recentContact, boolean isClear) {
		
//		if (listItem == null) return;
		
		// 声明变量，将对象缓存到本地（可以提高性能）
		int resourceId = -1;
		int eventCounts = 0;
		
		HashMap<String, Object> map = new HashMap<String, Object>();
		resourceId = observer.getResourceForWidget(recentContact);
		eventCounts = recentContact.getRecentEvents().size();
		map.put("name", recentContact.getDisplayName());
		map.put("eventcounts", eventCounts > 1 ? "("+String.valueOf(eventCounts)+")" : "");
		map.put("calltype", Integer.toString(resourceId));
		map.put("location", dataCacheWrapper.revealNumber(recentContact.getNumber()));
		map.put("date", Utils.formatDate(Utils.DEFAULT_24H_DATE_FORMATS, recentContact.getMostRecentDate()));
		
		//listItem.get(location).get("name").equals(o)
		
		try {
		
			HashMap<String, Object> item = null;
			
			item = listItem.get(location);
			
			if (item != null) {
				if (item.get("name").equals(recentContact.getDisplayName())) {
					listItem.remove(location);
				}
			}
		} catch(IndexOutOfBoundsException o){
			o.printStackTrace();
		}
		
//		if (location <= listItem.size() - 1 
//				&& (location > 0 || listItem.size() == recentContacts.size())) {
//			listItem.set(location, map);
//		}
//		else
		listItem.add(location, map);
	}
	
	
	@Override
	protected void onResume() {
		super.onResume();
		
		getContentResolver().registerContentObserver(
				CallLog.CONTENT_URI,
				false, callLogObserver );
		
	}
	
	@Override
	protected void onDestroy() {
		super.onDestroy();
		
		getContentResolver().unregisterContentObserver(callLogObserver);
		
		// 释放对象，释放内存
		if (callLogObserver != null)
			callLogObserver = null;
		
//		if (listItem != null)	
//			listItem = null;
		
		if (lvAdapter != null)
			lvAdapter = null;
		
		if (lv != null)
			lv = null;
		
//		if (recentContacts != null)
//			recentContacts = null;
		
	}
	
	/**
	 * Build RecentEvent.
	 * @param context
	 * @param intent
	 */
	private void buildRecentEvents(Context context, Intent intent, IRecentContactChangedListener listen) {
		
		observer = new CallLogDao();
		recentContacts = observer.update(recentContacts, intent, context, listen);

	}
	
	private CallLogNotificationObserver callLogObserver;
	
	private class CallLogNotificationObserver extends ContentObserver {

		private Context mContext;
		// too many threads to can't handle.
//		private Handler mHandler; 
		
		public CallLogNotificationObserver(Context context, Handler handler) {
			super(handler);
			
			mContext = context;
//			mHandler = handler;
		}
		
		@Override
		public void onChange(boolean selfChanged) {
			
			Log.i(TAG, "Track thread if running,[mRunning=" + mRunning + "]");
			
			if (mRunning) return;
			
			int cnt = 0;
			
			Cursor c = mContext.getContentResolver()
				.query(Calls.CONTENT_URI, 
						projection, 
						null, null, 
						Calls.DEFAULT_SORT_ORDER);
			
			if (c != null) {
				
				cnt = c.getCount();
				
				if (mRecords < cnt){
					
					if (c.moveToFirst()) {
						new DataLoading().execute(ACTION);
					}
					
				} else {
					
					recentContacts.clear();
					listItem.clear();
					
					new DataLoading().execute();
				}

				
				// reset mRecords.
				mRecords = cnt;
				// close cursor
				c.close();
				
				mRunning = true;
			}
		}
	}  	
	
}
